#include <Riostream.h>
#include <TString.h>

#include <CpLog.h>

#include "CpMagneticField.h"

ClassImp(CpMagneticField);

//_________________________________________________________________
CpMagneticField::CpMagneticField(): TObject(),
    fMagneticParticle(),
    fMapType(kMapOneType),
    fAnalyticFunction(0) {
//=====================
// Constructor
//=====================
}

//_________________________________________________________________
CpMagneticField::~CpMagneticField() {
//=====================
// Destructor
//=====================
}

//_________________________________________________________________
void CpMagneticField::Print() {
//=====================
// Prints info
//=====================

  CpInfo(Form("Mi_0\t= %e ", Mi_0()));
  CpInfo(Form("V_p\t= %e ", fMagneticParticle.Volume()));
  CpInfo(Form("M_p\t= %e ", M_p()));
  CpInfo(Form("dH\t= %e ", GradientOfMagneticField(fMagneticFieldType, 1.0)));

  CpInfo(Form("F_m\t= %e ", Force()));
}
Double_t Force();
//_________________________________________________________________
Double_t CpMagneticField::Force(Double_t value) {
//=====================
// Calculate Force of the magnetic field
//=====================

  return Mi_0()*fMagneticParticle.Volume()*M_p()*GradientOfMagneticField(fMagneticFieldType, value);
}


//_________________________________________________________________
Double_t CpMagneticField::GradientOfMagneticField(EMagneticField type, Double_t value) {
//=====================
// Calculate Gradient of the magnetic field
//=====================
  switch (type) {
  case kAnalytic:
    return GradientOfMagneticFieldAnalytic(value);
  case kMap:
    return 2.0;
  default:
    CpError("Wrong parameter of the field. Returning 0.0 ...");
  }
  return 0.0;
}

//_________________________________________________________________
Double_t CpMagneticField::GradientOfMagneticFieldAnalytic(Double_t value) {
//=====================
// Calculate Gradient of the magnetic field by analytic type
//=====================

  if (!fAnalyticFunction) {
    CpError("Analytic function is not defined !!! Returning 0.0");
    return 0.0;
  }
  return fAnalyticFunction->Derivative(value);
}

//_________________________________________________________________
void CpMagneticField::SetAnalyticFunction(TString functionString, Double_t min, Double_t max) {
//=====================
// Calculate Gradient of the magnetic field by analytic type
//=====================

  if (fAnalyticFunction) {
    delete fAnalyticFunction;
    fAnalyticFunction = 0;
  }

  fAnalyticFunction = new TF1("func", functionString.Data(), min, max);

}

//_________________________________________________________________
Double_t CpMagneticField::ValueAtAnalyticFunction(Double_t value) {
//=====================
// Calculate Gradient of the magnetic field by analytic type
//=====================

  if (fAnalyticFunction) {
    CpError("Analytic function is not defined !!! Returning 0.0");
    return 0.0;
  }

  return fAnalyticFunction->Eval(value);

}
